﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Demo.DtoParameters;
using Demo.Emuns;
using Demo.Entities;
using Demo.Helpers;
using Demo.Models.Dto;
using Microsoft.AspNetCore.Mvc;
using Demo.Services;
using Marvin.Cache.Headers;
using Newtonsoft.Json;

namespace Demo.Controllers
{
    [ApiController]
    public class CompaniesController : ControllerBase
    {
        private readonly ICompanyService _companyService;
        private readonly IMapper _mapper;

        public CompaniesController(IMapper mapper,ICompanyService companyService)
        {
            _companyService = companyService ?? throw new ArgumentNullException(nameof(companyService));
            _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
        }

        [HttpCacheExpiration(CacheLocation = CacheLocation.Public,MaxAge = 120)]
        [HttpCacheValidation(MustRevalidate = true)]
        [HttpGet("api/companies",Name = nameof(GetCompanies))]
        public async Task<IActionResult> GetCompanies([FromQuery] CompanyDtoParameters parameters)
        {
            var companies = await _companyService.GetCompaniesAsync(parameters);

            var previousLink = companies.HasPrevious ? GenPageUrl(parameters, ResourceUriType.Previous) : null;
            var nextLink = companies.HasNext ? GenPageUrl(parameters, ResourceUriType.Next) : null;

            var paginationMetadata = new
            {
                totalCount = companies.TotalCount,
                pageSize = companies.PageSize,
                currentPage = companies.CurrentPage,
                totalPage = companies.TotalPage,
                previousLink,
                nextLink
            };

            Response.Headers.Add("X-Pagination", JsonConvert.SerializeObject(paginationMetadata));

            var companiesDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);

            return Ok(companiesDto.ShapeData(parameters.Filds));
        }

        [HttpGet("api/companies/{companyIds}", Name = nameof(GetCompany))]
        public async Task<ActionResult<IEnumerable<CompanyDto>>> GetCompany(IEnumerable<Guid> companyIds)
        {
            var companies = await _companyService.GetCompaniesAsync(companyIds);

            if (companies == null)
            {
                return NotFound("未找到公司");
            }

            var companiesDto = _mapper.Map<IEnumerable<CompanyDto>>(companies);

            return Ok(companiesDto);
        }

        [HttpPost("api/companies")]
        public async Task<ActionResult<IEnumerable<CompanyDto>>> CreateCompany([FromBody] IEnumerable<CompanyAddDto> companies)
        {
            var entityArray = _mapper.Map<IEnumerable<Company>>(companies);

            await _companyService.AddCompanies(entityArray);

            var companyDtos = _mapper.Map<IEnumerable<CompanyDto>>(entityArray);

            var ids = string.Join(",", companyDtos.Select(x => x.Id));

            return CreatedAtRoute(nameof(GetCompany), new {companyIds = ids}, companyDtos);

        }

        [HttpDelete("api/companies/{companyId}")]
        public async Task<IActionResult> DeleteCompany(Guid companyId)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound("未找到需要删除的公司");
            }

            var companyEntity = await _companyService.GetCompanyAsync(companyId);

            _companyService.DeleteCompany(companyEntity);

            return NoContent();
        }

        private string GenPageUrl(CompanyDtoParameters parameters, ResourceUriType resourceUriType)
        {

            var param = new CompanyDtoParameters()
            {
                Filds =  parameters.Filds,
                CompanyName = parameters.CompanyName,
                SearchTerm = parameters.SearchTerm,
                PageSize = parameters.PageSize
            };

            switch (resourceUriType)
            {
                case ResourceUriType.Previous:
                {
                    param.PageNumber = parameters.PageNumber - 1;
                    return Url.Link(nameof(GetCompanies), param);
                }

                case ResourceUriType.Next:
                {
                    param.PageNumber = parameters.PageNumber + 1;
                    return Url.Link(nameof(GetCompanies), param);
                }
                default:
                {
                    param.PageNumber = parameters.PageNumber;
                    return Url.Link(nameof(GetCompanies), param);
                }
            }
        }
    }
}